#include "qbinaryrpc_response.h"
#include "qbinaryrpc_statics.h"

using namespace qbinaryrpc;

Response::Response()
    : id(-1),
      is_null(true),
      is_fault(false),
      fault_code(-1) {}

Response::Response(int id, const QVariant &return_value)
    : id(id),
      is_null(false),
      is_fault(false),
      fault_code(-1),
      return_value(return_value) {}

Response::Response(int id, int fault_code, const QString &fault_string)
    : id(id),
      is_null(false),
      is_fault(true),
      fault_code(fault_code), 
      fault_string(fault_string) {}

int Response::getId() const {
  return id;
}

bool Response::isNull() const {
  return is_null;
}

bool Response::isFault() const {
  return is_fault;
}

int Response::getFaultCode() const {
  return fault_code;
}

QString Response::getFaultString() const {
  return fault_string;
}

QVariant Response::getReturnValue() const {
  return return_value;
}

bool Response::setContent(const QByteArray &massive, int &now_position) {
  int massive_size(massive.size()), id_temp;
  if(Statics::decodeInt32(massive,
                          massive_size - 1,
                          now_position,
                          id_temp) == false) return false;
  int length_packet;
  if(Statics::decodeInt32(massive,
                          massive_size - 1,
                          now_position,
                          length_packet) == false) return false;
  int max_position(now_position + length_packet - 9);
  char type;
  if(Statics::decodeChar(massive,
                         massive_size - 1,
                         now_position,
                         type) == false) return false;
  if(type == 0x00) {
    if(Statics::decodeValue(massive,
                            max_position,
                            now_position,
                            &return_value) == false) return false;
    is_null = false;
    is_fault = false;
    fault_code = -1;
    fault_string.clear();
  } else if(type == 0x01) {
    int fault_code_temp;
    if(Statics::decodeInt32(massive,
                            max_position,
                            now_position,
                            fault_code_temp) == false) return false;
    QString fault_string_temp;
    if(Statics::decodeString(massive,
                             max_position,
                             now_position,
                             fault_string_temp) == false) return false;
    is_null = false;
    is_fault = true;
    fault_code = fault_code_temp;
    fault_string = fault_string_temp;
    return_value.clear();
  } else {
    return false;
  }
  id = id_temp;
  return true;
}

QByteArray Response::composeResponse() const {
  QByteArray body;
  if(is_null) return body;
  if(is_fault) {
    Statics::encodeChar(0x01, body);
    Statics::encodeInt32(fault_code, body);
    Statics::encodeString(fault_string, body);
  } else {
    Statics::encodeChar(0x00, body);
    if(Statics::encodeValue(return_value, body) == false)
      return QByteArray();
  }
  QByteArray header;
  Statics::encodeInt32(id, header);
  Statics::encodeInt32(body.size() + 8, header);
  return header + body;
}
